from khronos.des import Request
from khronos.utils import Deque

class Socket(object):
    """Implements one end of a full duplex connection. The connection can be used for 
    synchronized sharing of any kind of information through the use of a message queue."""
    def __init__(self, destination=None):
        self.__destination = None
        self.__requests = Deque()
        self.__queue = Deque()
        if destination is not None:
            self.connect(destination)
            
    def __repr__(self):
        return "%s(%s)" % (self.__class__.__name__, list(self.__queue))
        
    def connect(self, dst):
        self.__destination = dst
        if dst.disconnected():
            dst.connect(self)
            
    def disconnect(self):
        self.__destination = None
        if self.__destination.connected():
            self.__destination.disconnect()
            
    def connected(self):
        return self.__destination is not None
        
    def disconnected(self):
        return self.__destination is None
        
    def destination(self):
        return self.__destination
        
    def queue(self):
        return iter(self.__queue)
        
    def queue_size(self):
        return len(self.__queue)
        
    def get(self, blocking=True):
        if blocking:
            req = Request(deploy=self.__requests.insert_sorted, 
                          retract=self.cancel_get)
            if self.__queue:
                req.satisfy(self.__queue.popleft())
            return req
        else:
            return self.__queue.popleft()
            
    def cancel_get(self, req):
        self.__requests.remove_sorted(req, exact=True)
        
    def send(self, obj):
        self.__destination.receive(obj)
        
    def receive(self, obj):
        if self.__requests:
            self.__requests.popleft().satisfy(obj)
        else:
            self.__queue.append(obj)
            
